jaf.namespace("jaf.launcher");

/**
 * Simple DOM utility functions
 * @author anaik
 */
jaf.launcher.DomUtil = function()   {
   // The xhtml namespace URI
   var XHTMLNS = "http://www.w3.org/1999/xhtml";
   
   // Elements that are empty and have no content (for serializing)
   var emptyHtmlElements = [
      "br",
      "hr",
      "img",
      "link"
   ];
   
   /**
    * Serializes the specified DOM element to String
    * @param domElem The element or document to serialize as string
    * @param bDeep if true will recursively serialize the children of this element
    * @return the serialized form of the DOM element. i.e. String
    */
   function _asXmlString(domElem, bDeep)   {
      if(! domElem)  {return null;}
      var nodeType = domElem.nodeType;
      
      if(nodeType != 9 && nodeType != 1)  {
         throw new Error("Only Document and Element node supported");
      }
      
      if(nodeType == 9)  {
         domElem = domElem.documentElement;
      }
      
      var tagName = domElem.tagName;
      var attrs = domElem.attributes || new Array();
      var nsURI = DomUtil.getNamespaceURI(domElem);
      var xmlString = "";
      
      xmlString = "<" + tagName;
      // append the attributes
      var i;
      for(i = 0, len = attrs.length; i < len; i++)   {
         var attr = attrs[i];
         var attName = attr.nodeName;
         var nodeValue = attr.nodeValue;
         if(nodeValue) {
         	nodeValue = jaf.core.Util.escapeXml(nodeValue);
         }
         xmlString += " " + attName + "='" + nodeValue + "'";
      }
      
      if(!bDeep)  {
         xmlString += "/>";
         return xmlString;
      }else {
         if(nsURI == DomUtil.XHTMLNS || nsURI == ""  || nsURI == null)  {
            // optimizations for empty html tags
            if(emptyHtmlElements.indexOf(tagName) != -1)  {
               xmlString += " />";
               return xmlString;
            }
         }
         xmlString += ">";
      }
      
      // children
      var childNodes = domElem.childNodes;
      for(i = 0, len = childNodes.length; i < len; i++)   {
         var child = childNodes[i];
         nodeType = child.nodeType;
         
         if(nodeType == 1) { // Element
            xmlString += DomUtil._asXmlString(child, true);
         }else if(nodeType == 3) { // Text node
            xmlString += jaf.core.Util.escapeXml(child.nodeValue);
         }else if(nodeType == 4) { // CDATA Section
            xmlString += "<![CDATA[" + child.nodeValue + "]]>";
         }else if(nodeType == 5 || nodeType == 6) { // entity node
            xmlString += child.nodeName;
         }else if(nodeType == 8) { // Comment
            xmlString += "<!-- " + child.nodeValue + " -->"
         }
      }
      
      // end tag
      xmlString += "</" + tagName + ">";
      return xmlString;
   }
   
   function getElementsByAttributeNode(attrName, attrVal, optTagName, domElem)   {
      var elems = [];
      domElem = domElem || document;
      var children = domElem.getElementsByTagName(optTagName || "*");
      
      for(var i = 0, len = children.length; i < len; i++)   {
         var child = children[i];
         if(child.getAttribute(attrName) === attrVal)   {
            elems.push(child);
         }
      }
      return elems;
   }
   
   return   {
      /**
       * Serializes the specified dom element to a string
       */
      asXmlString: function(domElem)   {
         if(! domElem)  {return null;}
         if(domElem.xml)   {
            return domElem.xml;
         }
         if(domElem.outerHTML)   {
            return domElem.outerHTML;
         }
         return _asXmlString(domElem, true) 
      },
   
      /**
       * Gets the NS URI of the specified DOM element
       */
      getNamespaceURI: function(domElem)   {
         if(domElem.namespaceURI)   {
            return domElem.namespaceURI;
         }else {
            // for IE
            var tagUrn = domElem.tagUrn || "";
            return tagUrn.length > 0 ? tagUrn : DomUtil.XHTMLNS;
         }
      },
      
      /**
       * Creates a DOM element from the given string
       */
      asXmlDom: function(xmlStr) {
         var doc = null;
         var MOZ = (navigator.userAgent.indexOf("Gecko") != -1);
         var IE =  (navigator.userAgent.indexOf("MSIE") != -1);
         if(IE) {
            doc = new ActiveXObject("Microsoft.XMLDOM");
         } else if(MOZ) {
            try {
               var parser = new DOMParser();
               doc = parser.parseFromString(xmlStr,"text/xml");
            } catch(e) {
               alert(e.message);
            }
         }
         return doc;
      },

      /**
       * creates xml document object with specified information 
       * strQName - Qualified name of document root ele
       * strNsURI [optional] - the namespace URI of document
       * docType  [optional]-  doc type of document.
       */
      createXmlDocument: function(strQName, strNsURI, docType) {
         strNsURI = strNsURI || "";
         var domImpl = document.implementation;
         if(domImpl.createDocument) {
            return domImpl.createDocument(strNsURI, strQName, docType);
         }else {
            var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            var node = xmlDoc.createNode(1, strQName, strNsURI);
            xmlDoc.documentElement = node;
            return xmlDoc;
         }
      },
      
      byId:function(strId) {
         return document.getElementById(strId);
      },
      
      byClass: function(strClass)   {
         if(typeof document.getElementsByClassName === "function")   {
            return document.getElementsByClassName(strClass);
         }
         return getElementsByAttributeNode("class", strClass);
      }
   }
}();
